/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.simba.coherence;

import com.hp.hpl.jena.query.Query;
import com.hp.hpl.jena.query.QueryExecution;
import com.hp.hpl.jena.query.QueryExecutionFactory;
import com.hp.hpl.jena.query.QueryFactory;
import com.hp.hpl.jena.query.QuerySolution;
import com.hp.hpl.jena.query.ResultSet;
import java.util.Set;
import java.util.TreeSet;
import org.apache.log4j.Logger;
import org.simba.utils.Configuration;

/**
 *
 * @author ngonga
 */
public class EdgeCountCoherence implements CoherenceFunction {
    static Logger logger = Logger.getLogger("AEON");
    public int DIRECT_EDGE_FACTOR = 10;
    /** Computes the log of the number of edges between uri1 and uri2
     * 
     * @param uri1 First URI
     * @param uri2 Second URI
     * @param endpoint SPARQL Endpoint
     * @param graph Graph (null if not needed)
     * @return Score
     */
    @Override
    public double getCoherence(String uri1, String uri2, String endpoint, String graph) {
        if(uri1.equals(uri2)) return -1;
        //first get direct edges
        //logger.info("Getting direct edges between <"+uri1+"> and <"+uri2+">");
        String query = "SELECT ?p WHERE {{<"+uri1+"> ?p <"+uri2+">} UNION {<"+uri2+"> ?p <"+uri1+">}}" ;
        Query sparqlQuery = QueryFactory.create(query);
        QueryExecution qexec;
        if (graph != null) {
            qexec = QueryExecutionFactory.sparqlService(endpoint, sparqlQuery, graph);
        } else {
            qexec = QueryExecutionFactory.sparqlService(endpoint, sparqlQuery);
        }
        ResultSet results = qexec.execSelect();
        int count = 0;
        try {
            while (results.hasNext()) {
                QuerySolution soln = results.nextSolution();
                count++;
            }
        } catch (Exception ex) {
            ex.printStackTrace();
            logger.warn(ex.getMessage());
        }
        count = count * DIRECT_EDGE_FACTOR;
        //then indirect edges
        //logger.info("Getting indirect edges between "+uri1+" and "+uri2);
        query = "SELECT ?p WHERE {{<"+uri1+"> ?p ?y} UNION {?y ?p <"+uri1+">}. "
                + "{<"+uri2+"> ?q ?y} UNION {?y ?q <"+uri2+">}}" ;
        sparqlQuery = QueryFactory.create(query);
        if (graph != null) {
            qexec = QueryExecutionFactory.sparqlService(endpoint, sparqlQuery, graph);
        } else {
            qexec = QueryExecutionFactory.sparqlService(endpoint, sparqlQuery);
        }
        results = qexec.execSelect();        
        try {
            while (results.hasNext()) {
                QuerySolution soln = results.nextSolution();
                count++;
            }
        } catch (Exception ex) {
            ex.printStackTrace();
            logger.warn(ex.getMessage());
        }
        
        return Math.log(count+1);
    }

    
    /** Batch version of coherence computation
     * 
     * @param uris Set of URIs
     * @param endpoint Endpoint
     * @param graph Graph (null if not needed)
     * @return Coherence Matrix
     */
    @Override
    public CoherenceMatrix getCoherence(Set<String> uris, String endpoint, String graph) {
        CoherenceMatrix c = new SparseCoherenceMatrix();
        for(String uri1: uris)
        {
            for(String uri2: uris)
            {
                if(!uri1.equals(uri2))
                {
                    c.setCoherence(uri1, uri2, getCoherence(uri1, uri2, endpoint, graph));
                //logger.info("Coherence between "+uri1+" and "+uri2+" is "
                //        +c.getCoherence(uri1, uri2));                            
                }
            }
        }
        c.normRows();
        for(String uri1: uris)
        {
            c.setCoherence(uri1, uri1, 1.0);
        }
        return c;
    }
    
    public static void main(String args[])
    {
        EdgeCountCoherence ecc = new EdgeCountCoherence();
        TreeSet<String> uris = new TreeSet<String>();
        uris.add("http://dbpedia.org/resource/Jena,_Louisiana");
        uris.add("http://dbpedia.org/resource/Louisiana");
        uris.add("http://dbpedia.org/resource/Louisiana,_Missouri");
        System.out.println(ecc.getCoherence(uris, "http://live.dbpedia.org/sparql", null));
    }

    @Override
    public CoherenceMatrix getCoherence(Set<String> uris, Configuration c) {
        SparseCoherenceMatrix coherence = (SparseCoherenceMatrix)getCoherence(uris, c.sparqlEndpoint, c.graph);        
        //add tree distance information
        return coherence;
    }
}